package cn.iocoder.yudao.framework.qrcode.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.lang.PatternPool;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.crypto.symmetric.RC4;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.framework.common.biz.config.ConfigCommonApi;
import cn.iocoder.yudao.framework.common.biz.file.FileCommonApi;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.qrcode.pojo.QrCodeDataType;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import java.net.URL;

import static cn.iocoder.yudao.framework.constant.ConfigConstants.CONFIG_INFRA_QRCODE_HOST;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  这里是文件说明
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2025/01/04
 */
@SuppressWarnings("unused")
@Slf4j
@UtilityClass
public class QrCodeUtils {
    private static final int QRCODE_SIZE = 300;
    private static final RC4 RC_4 = new RC4("xianmin-mdyc");

    public static <T extends QrCodeDataType> String encryptData(T type) {
        return RC_4.encryptHex(JsonUtils.toJsonString(type));
    }

    public static String decryptData(String cryptData) {
        return RC_4.decrypt(cryptData);
    }

    @Nonnull
    public static <T extends QrCodeDataType> byte[] generatePng(@Nonnull T type) {
        return generatePng(type, null);
    }

    @Nonnull
    public static <T extends QrCodeDataType> byte[] generatePng(@Nonnull T type, @Nullable String logoUrl) {
        QrConfig config = new QrConfig();
        config.setWidth(QRCODE_SIZE);
        config.setHeight(QRCODE_SIZE);
        try {
            if (PatternPool.URL_HTTP.matcher(StrUtil.nullToDefault(logoUrl, "")).find()) {
                URL resource = URLUtil.url(logoUrl);
                if (resource != null) {
                    config.setImg(ImgUtil.read(resource));
                }
            } else {
                URL resource = ClassUtil.getClassLoader().getResource("public/logo.png");
                if (resource != null) {
                    config.setImg(ImgUtil.read(resource));
                }
            }
        } catch (Throwable e) {
            log.error("[generatePng] LOGO 读取出错", e);
        }
        try {
            byte[] bytes = QrCodeUtil.generatePng(buildUrl(type), config);
            if (bytes == null) {
                bytes = new byte[0];
            }
            return bytes;
        } catch (Throwable e) {
            log.error("[generatePng] 二维码生成出错", e);
        }
        return new byte[0];
    }

    @Nonnull
    public static <T extends QrCodeDataType> String generatePngAsUri(@Nonnull T type) {
        try {
            String path = "qrcode/" + type.getType() + "/";
            String fileName = type.hashCode() + ".png";
            path += fileName;
            FileCommonApi fileApi = SpringUtil.getBean(FileCommonApi.class);
            String url = fileApi.getUrlByPath(path);
            if (StrUtil.isBlank(url)) {
                url = fileApi.createFile(fileName, path, generatePng(type));
            }
            return url;
        } catch (Exception e) {
            return generatePngAsBase64Uri(type);
        }
    }

    @Nonnull
    public static <T extends QrCodeDataType> String generatePngAsBase64Uri(@Nonnull T type) {
        return generatePngAsBase64Uri(type, null);
    }

    @Nonnull
    public static <T extends QrCodeDataType> String generatePngAsBase64Uri(@Nonnull T type, @Nullable String logoUrl) {
        byte[] bytes = generatePng(type, logoUrl);
        if (bytes.length > 0) {
            return URLUtil.getDataUri("image/png", "base64", Base64.encode(bytes));
        }
        return "";
    }

    @Nonnull
    public static <T extends QrCodeDataType> String buildUrl(@Nonnull T type) {
        String host = null;
        try {
            host = SpringUtil.getBean(ConfigCommonApi.class).getConfigValueByKey(CONFIG_INFRA_QRCODE_HOST);
        } catch (Exception e) {
            log.error("[buildUrl] 获取二维码主机配置出错", e);
        }
        if (host == null) {
            host = "";
        }
        if (!host.contains("://")) {
            host = "https://" + host;
        }
        if (host.endsWith("/")) {
            host = host.substring(0, host.length() - 1);
        }
        String parameter = type.toParameter();
        if (parameter == null) {
            parameter = "";
        } else if (!parameter.contains("?")) {
            parameter = "?" + parameter;
        }
        return host + parameter;
    }

}
